package datagram;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

public class Histogram extends Datagram {
	public int 				points, maps;
	public int 				bins, res;
	private int				value[][][]			= null;
	private double			valueNormal[][][]	= null;
	
	public Histogram( BufferedImage image, int res, int bins ) {
		super(image);
		this.res = res;
		this.bins = bins;
		calculate();
	}

	@Override
	public double calculate() {
		if (image == null) {
			System.out.println("ERROR: histogram image not loaded");
			return 1.0;
		}
		
		double binw = 256.0/bins;
		double mapw, maph;
		int color, mapi, mapj, bini;
		int maxx = 0,
			maxy = 0,
			minx = image.getWidth(),
			miny = image.getHeight();
		
		this.res = res;
		this.bins = bins;
		value = new int[res][res][bins];
		valueNormal = new double[res][res][bins];
		
		// Find true region of interest
		for (int y = 0; y < image.getHeight(); y++) {
			for (int x = 0; x < image.getWidth(); x++) {
				color = image.getRGB(x,y) & 0x000000FF;
				if (color < 255) {
					if (x < minx) minx = x;
					if (y < miny) miny = y;
					if (x > maxx) maxx = x;
					if (y > maxy) maxy = y;
				}
			}
		}
		
		mapw = (maxx - minx)*1.0/res;
		maph = (maxy - miny)*1.0/res;
		points = (int) (mapw*maph);
		maps = res*res;

		// Build histogram
		for (int y = miny; y < maxy; y++) {
			for (int x = minx; x < maxx; x++) {
				color = image.getRGB(x,y) & 0x000000FF;
				
				bini = (int) (color/binw);
				mapi = (int) ((x - minx)*1.0/mapw);
				mapj = (int) ((y - miny)*1.0/maph);
				//System.out.println("[" + x + ", " + y + ", " + color + "] = [" + mapi + ", " + mapj + ", " + bini + "]");
				value[mapi][mapj][bini]++;
			}
		}
		
		for (int i = 0; i < res; i++)
			for (int j = 0; j < res; j++)
				for (int b = 0; b < bins; b++)
					valueNormal[i][j][b] = value[i][j][b]*1.0/points;
		
		return 0.0;
	}
	
	@Override
	public double difference( Datagram other ) {
		if (!(other instanceof Histogram))
			return 1.0;
		
		Histogram hist = (Histogram) other;
		double diff = 0;
		int res = valueNormal.length;
		
		for (int i = 0; i < res; i++)
			for (int j = 0; j < res; j++)
				for (int b = 0; b < bins; b++)
					diff += Math.abs(valueNormal[i][j][b] - hist.valueNormal[i][j][b]);
		
		return diff / (points*res*res);
	}
}
